/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-11-06     balanceTWK   first version
 */

#include <stdint.h>
#include <rthw.h>
#include <rtthread.h>
#include <string.h>
#include <board.h>
#include "stdio.h"

#ifdef BSP_USING_SRAM
#include "drv_sram.h"
#endif

#define MY_PRINTF_DEVICE_NAME "uart2"

static rt_device_t my_printf_device;

void Set_USBClock(void);
void JTAGPortInit(void);

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler */
    /* User can add his own implementation to report the HAL error return state */
    while (1)
    {
    }
    /* USER CODE END Error_Handler */
}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{
    SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
    NVIC_SetPriority(SysTick_IRQn, 0);
}

/**
 * This is the timer interrupt service routine.
 *
 */
void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}

/**
 * This function will initial N32 board.
 */
void rt_hw_board_init()
{


    /* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x10000000 */
    SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endif

#ifdef BSP_USING_SRAM
    rt_system_heap_init((void *)EXT_SRAM_BEGIN, (void *)EXT_SRAM_END);
#else
    rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif

    SystemClock_Config();
    Set_USBClock();  /*Configures USB Clock input (48MHz)*/

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
    /* JTAG-DP Disabled and SW-DP Enabled */
    GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);
    JTAGPortInit();

#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif
    my_printf("rt_console_set_device start! tick=%d\n",rt_tick_get());
#ifdef RT_USING_CONSOLE
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
    my_printf("rt_console_set_device end! tick=%d\n",rt_tick_get());

}
/**
 * @brief  Configures JTAG GPIO.
 */
void JTAGPortInit(void)
{
    GPIO_InitType GPIO_InitStructure;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOB, ENABLE);
    /* Configure PA.13 (JTMS/SWDAT), PA.14 (JTCK/SWCLK) and PA.15 (JTDI) as
    output push-pull */
    /*GPIO_InitStructure.Pin        = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);*/

    /* Configure PB.03 (JTDO) and PB.04 (JTRST) as output push-pull */
    GPIO_InitStructure.Pin = /*GPIO_PIN_3 | */GPIO_PIN_4;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOB,GPIO_PIN_4);
}
/**
 * This function will print a formatted string on system console
 *
 * @param fmt the format
 */
rt_uint32_t my_printf(const char *fmt, ...)
{
    va_list args;
    rt_uint32_t length;
    static char log_buf[RT_CONSOLEBUF_SIZE];
    rt_err_t result = RT_EOK;


    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = vsnprintf(log_buf, sizeof(log_buf) - 1, fmt, args);

    if (my_printf_device == RT_NULL)
    {
        my_printf_device = rt_device_find(MY_PRINTF_DEVICE_NAME);
        if (my_printf_device != RT_NULL)
        {
            result = rt_device_open(my_printf_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX |  RT_DEVICE_FLAG_STREAM);

            if (RT_EOK == result) {
                rt_device_write(my_printf_device, 0, log_buf, length);
            }
        }
    }
    else {
        rt_device_write(my_printf_device, 0, log_buf, length);
    }


    va_end(args);

    return length;
}
